﻿using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using com.reltru.GDI;

namespace ScreenGenie
{
    public partial class frmMain : Form
    {
        [DllImport("kernel32.dll")]
        public static extern int GetTickCount();

        [DllImport("user32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags);

        const int DEFAULT_durationS = 30;
        const int DEFAULT_delayMS = 0;
        const int DEFAULT_minR = 0;
        const int DEFAULT_minG = 0;
        const int DEFAULT_minB = 0;
        const int DEFAULT_maxR = 255;
        const int DEFAULT_maxG = 255;
        const int DEFAULT_maxB = 255;
        const int DEFAULT_colorDistance = 0;
        const int DEFAULT_increments = 1;
        const int DEFAULT_minRadius = 50;
        const int DEFAULT_maxRadius = 50;
        const int DEFAULT_minWidth = 10;
        const int DEFAULT_maxWidth = 10;
        const int DEFAULT_minHeight = 10;
        const int DEFAULT_maxHeight = 10;

        string xmlFile;
        System.Xml.XmlDocument xmlDoc;
        System.Xml.XmlElement xmlElement;
        System.Xml.XmlNodeList xmlNodeList;
        System.Xml.XmlNode xmlNode;

        Drawing gdi;
        bool RUNNING;

        public frmMain()
        {
            InitializeComponent();
            this.KeyPress += new KeyPressEventHandler(frmMain_KeyPress);
            this.Load += new System.EventHandler(frmMain_Load);
        }

        private void frmMain_Load(object sender, System.EventArgs e)
        {
            if (!loadConfiguration()) Application.Exit();

            this.Opacity = 100;
            this.Show();

            SetWindowPos(this.Handle, -1, 0, 0, 0, 0, 0x0002 | 0x0001);

            hideMouse();

            RUNNING = true;

            gdi = new Drawing();
            gdi.getDC(this.CreateGraphics());

            xmlNodeList = xmlElement.SelectNodes("/ScreenGenie/Run/*");

            foreach (System.Xml.XmlNode xmlNode in xmlNodeList)
            {
                xmlParse(xmlNode.SelectSingleNode("Type").InnerText, xmlNode);
            }

            /////
            //
            // Manual Examples 
            //
            //      drawCircles(10, 100, 50, 150, new RGB(0, 0, 0), new RGB(255, 255, 255));
            //      drawColor_Gradient(10, 30, new RGB(0, 0, 0), new RGB(255, 255, 255), 20, 100);
            //      drawColor_Random(10, 300, new RGB(0, 0, 0), new RGB(255, 255, 0));
            //      drawColor_Toggle(10, 1000, new RGB(128, 128, 128), new RGB(255, 255, 255));
            //      drawLines_Diagonals(10, 0, new RGB(128, 0, 0), new RGB(255, 0, 0));
            //      drawLines_ScrollDown(10, 20, new RGB(128, 128, 0), new RGB(255, 255, 0));
            //      drawLines_ScrollLeft(10, 20, new RGB(128, 128, 0), new RGB(255, 255, 0));
            //      drawLines_ScrollRight(10, 20, new RGB(128, 128, 0), new RGB(255, 255, 0));
            //      drawLines_ScrollUp(10, 20, new RGB(128, 128, 0), new RGB(255, 255, 0));
            /////

            frmMain_Unload();
        }

        private void frmMain_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)Keys.Escape) RUNNING = false;
        }

        private void frmMain_Unload()
        {
            showMouse();
            gdi.releaseDC();
            Application.Exit();
        }

        //
        //
        // Non-Form Functions
        //
        //

        private int clamp(int _val, int _min, int _max)
        {
            return Math.Max(_min, Math.Min(_val, _max));
        }

        private void drawCircles(int _durationS, int _delayMS, int _minRadius, int _maxRadius, RGB _minColor, RGB _maxColor, bool _fill, bool _altColors)
        {
            int startTick = GetTickCount();

            Random rnd = new Random();

            int x, y;
            int r, g, b;
            int rad;
            int alt = 1;

            while (GetTickCount() - startTick < _durationS * 1000 && RUNNING)
            {
                x = rnd.Next(0, this.Width);
                y = rnd.Next(0, this.Height);

                if (_altColors)
                {
                    alt++; if (alt > 1) alt = 0;
                    if (alt == 0)
                    {
                        r = _minColor.r;
                        g = _minColor.g;
                        b = _minColor.b;
                    }
                    else
                    {
                        r = _maxColor.r;
                        g = _maxColor.g;
                        b = _maxColor.b;
                    }
                }
                else
                {
                    r = rnd.Next(_minColor.r, _maxColor.r);
                    g = rnd.Next(_minColor.g, _maxColor.g);
                    b = rnd.Next(_minColor.b, _maxColor.b);
                }

                rad = rnd.Next(_minRadius, _maxRadius);

                if (_fill)
                {
                    gdi.createSolidBrushSelect(r, g, b);
                    gdi.createPenSelect(0, 1, r, g, b);
                }
                else
                {
                    gdi.createPenSelect(0, 1, r, g, b, StockObjects.HOLLOW_BRUSH);
                }
                gdi.drawCircle(x, y, rad);

                sleep(_delayMS);
            }
        }

        private void drawColor_Gradient(int _durationS, int _delayMS, RGB _minColor, RGB _maxColor, int _colorDistance, int _increments, bool _altColors)
        {
            int startTick = GetTickCount();

            Random rnd = new Random();

            int r, g, b;
            int oR = 0, oG = 0, oB = 0;
            double iR, iG, iB;
            int i;
            int alt = 1;

            while (GetTickCount() - startTick < _durationS * 1000 && RUNNING)
            {
                if (_altColors)
                {
                    alt++; if (alt > 1) alt = 0;
                    if (alt == 0)
                    {
                        r = _minColor.r;
                        g = _minColor.g;
                        b = _minColor.b;
                    }
                    else
                    {
                        r = _maxColor.r;
                        g = _maxColor.g;
                        b = _maxColor.b;
                    }
                }
                else
                {
                    i = 0; r = rnd.Next(_minColor.r, _maxColor.r); while (Math.Abs(r - oR) < _colorDistance && _colorDistance >= 15 && i < 50) { r = rnd.Next(_minColor.r, _maxColor.r); i++; }
                    i = 0; g = rnd.Next(_minColor.g, _maxColor.g); while (Math.Abs(g - oG) < _colorDistance && _colorDistance >= 15 && i < 50) { g = rnd.Next(_minColor.g, _maxColor.g); i++; }
                    i = 0; b = rnd.Next(_minColor.b, _maxColor.b); while (Math.Abs(b - oB) < _colorDistance && _colorDistance >= 15 && i < 50) { b = rnd.Next(_minColor.b, _maxColor.b); i++; }
                }

                iR = (double)(r - oR) / _increments;
                iG = (double)(g - oG) / _increments;
                iB = (double)(b - oB) / _increments;

                for (i = 0; i < _increments; ++i)
                {
                    if (!RUNNING) break;
                    gdi.fillScreen((uint)System.Drawing.ColorTranslator.ToWin32(System.Drawing.Color.FromArgb((int)(oR + iR * i), (int)(oG + iG * i), (int)(oB + iB * i))), this.Width, this.Height);
                    sleep(_delayMS);
                }

                gdi.fillScreen((uint)System.Drawing.ColorTranslator.ToWin32(System.Drawing.Color.FromArgb(r, g, b)), this.Width, this.Height);

                oR = r;
                oG = g;
                oB = b;

                sleep(_delayMS);
            }
        }

        private void drawColor_Fill(int _durationS, int _delayMS, RGB _minColor, RGB _maxColor, bool _altColors)
        {
            int startTick = GetTickCount();

            Random rnd = new Random();

            int r = 0, g = 0, b = 0;
            int alt = 1;

            while (GetTickCount() - startTick < _durationS * 1000 && RUNNING)
            {
                if (_altColors)
                {
                    alt++; if (alt > 1) alt = 0;
                    if (alt == 0)
                    {
                        r = _minColor.r;
                        g = _minColor.g;
                        b = _minColor.b;
                    }
                    else
                    {
                        r = _maxColor.r;
                        g = _maxColor.g;
                        b = _maxColor.b;
                    }
                }
                else
                {
                    r = rnd.Next(_minColor.r, _maxColor.r);
                    g = rnd.Next(_minColor.g, _maxColor.g);
                    b = rnd.Next(_minColor.b, _maxColor.b);
                }

                gdi.fillScreen((uint)System.Drawing.ColorTranslator.ToWin32(System.Drawing.Color.FromArgb(r, g, b)), this.Width, this.Height);

                sleep(_delayMS);
            }
        }

        private void drawEllipses(int _durationS, int _delayMS, int _minWidth, int _maxWidth, int _minHeight, int _maxHeight, RGB _minColor, RGB _maxColor, bool _fill, bool _altColors)
        {
            int startTick = GetTickCount();

            Random rnd = new Random();

            int x, y;
            int r, g, b;
            int alt = 1;

            while (GetTickCount() - startTick < _durationS * 1000 && RUNNING)
            {
                x = rnd.Next(0, this.Width);
                y = rnd.Next(0, this.Height);

                if (_altColors)
                {
                    alt++; if (alt > 1) alt = 0;
                    if (alt == 0)
                    {
                        r = _minColor.r;
                        g = _minColor.g;
                        b = _minColor.b;
                    }
                    else
                    {
                        r = _maxColor.r;
                        g = _maxColor.g;
                        b = _maxColor.b;
                    }
                }
                else
                {
                    r = rnd.Next(_minColor.r, _maxColor.r);
                    g = rnd.Next(_minColor.g, _maxColor.g);
                    b = rnd.Next(_minColor.b, _maxColor.b);
                }

                if (_fill)
                {
                    gdi.createSolidBrushSelect(r, g, b);
                    gdi.createPenSelect(0, 1, r, g, b);
                }
                else
                {
                    gdi.createPenSelect(0, 1, r, g, b, StockObjects.HOLLOW_BRUSH);
                }
                gdi.drawEllipse(x, y, rnd.Next(_minWidth, _maxWidth), rnd.Next(_minHeight, _maxHeight));

                sleep(_delayMS);
            }
        }

        private void drawLines_Diagonals(int _durationS, int _delayMS, RGB _minColor, RGB _maxColor, bool _altColors)
        {
            int startTick = GetTickCount();

            Random rnd = new Random();

            int x, y;
            int r, g, b;
            int alt = 1;

            while (GetTickCount() - startTick < _durationS * 1000 && RUNNING)
            {
                x = rnd.Next(0, this.Width);
                y = rnd.Next(0, this.Height);

                if (_altColors)
                {
                    alt++; if (alt > 1) alt = 0;
                    if (alt == 0)
                    {
                        r = _minColor.r;
                        g = _minColor.g;
                        b = _minColor.b;
                    }
                    else
                    {
                        r = _maxColor.r;
                        g = _maxColor.g;
                        b = _maxColor.b;
                    }
                }
                else
                {
                    r = rnd.Next(_minColor.r, _maxColor.r);
                    g = rnd.Next(_minColor.g, _maxColor.g);
                    b = rnd.Next(_minColor.b, _maxColor.b);
                }

                gdi.createPenSelect(0, 1, r, g, b);

                gdi.drawLine(0, 0, x, y);
                gdi.drawLine(this.Width, 0, x, y);
                gdi.drawLine(0, this.Height, x, y);
                gdi.drawLine(this.Width, this.Height, x, y);

                gdi.drawLine(this.Width, (int)(this.Height * 0.5), x, y);
                gdi.drawLine((int)(this.Width * 0.5), 0, x, y);
                gdi.drawLine(0, (int)(this.Height * 0.5), x, y);
                gdi.drawLine((int)(this.Width * 0.5), this.Height, x, y);

                gdi.drawLine(this.Width, (int)(this.Height * 0.25), x, y);
                gdi.drawLine((int)(this.Width * 0.25), 0, x, y);
                gdi.drawLine(0, (int)(this.Height * 0.25), x, y);
                gdi.drawLine((int)(this.Width * 0.25), this.Height, x, y);

                gdi.drawLine(this.Width, (int)(this.Height * 0.75), x, y);
                gdi.drawLine((int)(this.Width * 0.75), 0, x, y);
                gdi.drawLine(0, (int)(this.Height * 0.75), x, y);
                gdi.drawLine((int)(this.Width * 0.75), this.Height, x, y);

                sleep(_delayMS);
            }
        }

        private void drawLines_ScrollDown(int _durationS, int _delayMS, RGB _minColor, RGB _maxColor, bool _altColors)
        {
            int startTick = GetTickCount();

            Random rnd = new Random();

            int y, i;
            int r, g, b;
            int alt = 1;

            uint[] aLines = new uint[this.Height];

            for (i = 0; i < aLines.Length; ++i) { aLines[i] = 0; }

            while (GetTickCount() - startTick < _durationS * 1000 && RUNNING)
            {
                if (_altColors)
                {
                    alt++; if (alt > 1) alt = 0;
                    if (alt == 0)
                    {
                        r = _minColor.r;
                        g = _minColor.g;
                        b = _minColor.b;
                    }
                    else
                    {
                        r = _maxColor.r;
                        g = _maxColor.g;
                        b = _maxColor.b;
                    }
                }
                else
                {
                    r = rnd.Next(_minColor.r, _maxColor.r);
                    g = rnd.Next(_minColor.g, _maxColor.g);
                    b = rnd.Next(_minColor.b, _maxColor.b);
                }

                for (y = aLines.Length - 1; y > 0; --y) { aLines[y] = aLines[y - 1]; }

                aLines[0] = (uint)System.Drawing.ColorTranslator.ToWin32(System.Drawing.Color.FromArgb(r, g, b));

                for (y = 0; y < aLines.Length; ++y)
                {
                    gdi.createPenSelect(0, 1, aLines[y]);
                    gdi.drawLine(0, y, this.Width, y);
                }

                sleep(_delayMS);
            }
        }

        private void drawLines_ScrollLeft(int _durationS, int _delayMS, RGB _minColor, RGB _maxColor, bool _altColors)
        {
            int startTick = GetTickCount();

            Random rnd = new Random();

            int x, i;
            int r, g, b;
            int alt = 1;

            uint[] aLines = new uint[this.Width];

            for (i = 0; i < aLines.Length; ++i) { aLines[i] = 0; }

            while (GetTickCount() - startTick < _durationS * 1000 && RUNNING)
            {
                if (_altColors)
                {
                    alt++; if (alt > 1) alt = 0;
                    if (alt == 0)
                    {
                        r = _minColor.r;
                        g = _minColor.g;
                        b = _minColor.b;
                    }
                    else
                    {
                        r = _maxColor.r;
                        g = _maxColor.g;
                        b = _maxColor.b;
                    }
                }
                else
                {
                    r = rnd.Next(_minColor.r, _maxColor.r);
                    g = rnd.Next(_minColor.g, _maxColor.g);
                    b = rnd.Next(_minColor.b, _maxColor.b);
                }

                for (x = 0; x < aLines.Length - 1; ++x) { aLines[x] = aLines[x + 1]; }

                aLines[aLines.Length - 1] = (uint)System.Drawing.ColorTranslator.ToWin32(System.Drawing.Color.FromArgb(r, g, b));

                for (x = aLines.Length - 1; x >= 0; --x)
                {
                    gdi.createPenSelect(0, 1, aLines[x]);
                    gdi.drawLine(x, 0, x, this.Height);
                }

                sleep(_delayMS);
            }
        }

        private void drawLines_ScrollRight(int _durationS, int _delayMS, RGB _minColor, RGB _maxColor, bool _altColors)
        {
            int startTick = GetTickCount();

            Random rnd = new Random();

            int x, i;
            int r, g, b;
            int alt = 1;

            uint[] aLines = new uint[this.Width];

            for (i = 0; i < aLines.Length; ++i) { aLines[i] = 0; }

            while (GetTickCount() - startTick < _durationS * 1000 && RUNNING)
            {
                if (_altColors)
                {
                    alt++; if (alt > 1) alt = 0;
                    if (alt == 0)
                    {
                        r = _minColor.r;
                        g = _minColor.g;
                        b = _minColor.b;
                    }
                    else
                    {
                        r = _maxColor.r;
                        g = _maxColor.g;
                        b = _maxColor.b;
                    }
                }
                else
                {
                    r = rnd.Next(_minColor.r, _maxColor.r);
                    g = rnd.Next(_minColor.g, _maxColor.g);
                    b = rnd.Next(_minColor.b, _maxColor.b);
                }

                for (x = aLines.Length - 1; x > 0; --x) { aLines[x] = aLines[x - 1]; }

                aLines[0] = (uint)System.Drawing.ColorTranslator.ToWin32(System.Drawing.Color.FromArgb(r, g, b));

                for (x = 0; x < aLines.Length; ++x)
                {
                    gdi.createPenSelect(0, 1, aLines[x]);
                    gdi.drawLine(x, 0, x, this.Height);
                }

                sleep(_delayMS);
            }
        }

        private void drawLines_ScrollUp(int _durationS, int _delayMS, RGB _minColor, RGB _maxColor, bool _altColors)
        {
            int startTick = GetTickCount();

            Random rnd = new Random();

            int y, i;
            int r, g, b;
            int alt = 1;

            uint[] aLines = new uint[this.Height];

            for (i = 0; i < aLines.Length; ++i) { aLines[i] = 0; }

            while (GetTickCount() - startTick < _durationS * 1000 && RUNNING)
            {
                if (_altColors)
                {
                    alt++; if (alt > 1) alt = 0;
                    if (alt == 0)
                    {
                        r = _minColor.r;
                        g = _minColor.g;
                        b = _minColor.b;
                    }
                    else
                    {
                        r = _maxColor.r;
                        g = _maxColor.g;
                        b = _maxColor.b;
                    }
                }
                else
                {
                    r = rnd.Next(_minColor.r, _maxColor.r);
                    g = rnd.Next(_minColor.g, _maxColor.g);
                    b = rnd.Next(_minColor.b, _maxColor.b);
                }

                for (y = 0; y < aLines.Length - 1; y++) { aLines[y] = aLines[y + 1]; }

                aLines[aLines.Length - 1] = (uint)System.Drawing.ColorTranslator.ToWin32(System.Drawing.Color.FromArgb(r, g, b));

                for (y = aLines.Length - 1; y >= 0; y--)
                {
                    gdi.createPenSelect(0, 1, aLines[y]);
                    gdi.drawLine(0, y, this.Width, y);
                }

                sleep(_delayMS);
            }
        }

        private void drawRectangles(int _durationS, int _delayMS, int _minWidth, int _maxWidth, int _minHeight, int _maxHeight, RGB _minColor, RGB _maxColor, bool _fill, bool _altColors)
        {
            int startTick = GetTickCount();

            Random rnd = new Random();

            int x, y;
            int r, g, b;
            int alt = 1;

            while (GetTickCount() - startTick < _durationS * 1000 && RUNNING)
            {
                x = rnd.Next(0, this.Width);
                y = rnd.Next(0, this.Height);

                if (_altColors)
                {
                    alt++; if (alt > 1) alt = 0;
                    if (alt == 0)
                    {
                        r = _minColor.r;
                        g = _minColor.g;
                        b = _minColor.b;
                    }
                    else
                    {
                        r = _maxColor.r;
                        g = _maxColor.g;
                        b = _maxColor.b;
                    }
                }
                else
                {
                    r = rnd.Next(_minColor.r, _maxColor.r);
                    g = rnd.Next(_minColor.g, _maxColor.g);
                    b = rnd.Next(_minColor.b, _maxColor.b);
                }

                if (_fill)
                {
                    gdi.createSolidBrushSelect(r, g, b);
                    gdi.createPenSelect(0, 1, r, g, b);
                }
                else
                {
                    gdi.createPenSelect(0, 1, r, g, b, StockObjects.HOLLOW_BRUSH);
                }
                gdi.drawRectangle(x, y, rnd.Next(_minWidth, _maxWidth), rnd.Next(_minHeight, _maxHeight));

                sleep(_delayMS);
            }
        }

        private void hideMouse()
        {
            Cursor.Hide();
        }

        private bool loadConfiguration()
        {
            try
            {
                int x, y, width, height, min, max;
                Random rnd = new Random();

                xmlFile = System.IO.Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]) + "\\" + System.IO.Path.GetFileNameWithoutExtension(Environment.GetCommandLineArgs()[0]) + ".xml";

                xmlDoc = new System.Xml.XmlDocument();
                xmlDoc.Load(xmlFile);
                xmlElement = xmlDoc.DocumentElement;

                xmlNode = xmlElement.SelectSingleNode("/ScreenGenie/Layout/Location/X");
                if (xmlNode.Attributes.GetNamedItem("random").InnerText.ToLower() == "true" && int.TryParse(xmlNode.Attributes.GetNamedItem("min").InnerText, out min) && int.TryParse(xmlNode.Attributes.GetNamedItem("max").InnerText, out max))
                {
                    this.Left = (min < max) ? rnd.Next(min, max) : 0;
                }
                else
                {
                    this.Left = (int.TryParse(xmlNode.InnerText, out x)) ? x : 0;
                }

                xmlNode = xmlElement.SelectSingleNode("/ScreenGenie/Layout/Location/Y");
                if (xmlNode.Attributes.GetNamedItem("random").InnerText.ToLower() == "true" && int.TryParse(xmlNode.Attributes.GetNamedItem("min").InnerText, out min) && int.TryParse(xmlNode.Attributes.GetNamedItem("max").InnerText, out max))
                {
                    this.Top = (min < max) ? rnd.Next(min, max) : 0;
                }
                else
                {
                    this.Top = (int.TryParse(xmlNode.InnerText, out y)) ? y : 0;
                }

                xmlNode = xmlElement.SelectSingleNode("/ScreenGenie/Layout/Size/Width");
                if (xmlNode.Attributes.GetNamedItem("random").InnerText.ToLower() == "true" && int.TryParse(xmlNode.Attributes.GetNamedItem("min").InnerText, out min) && int.TryParse(xmlNode.Attributes.GetNamedItem("max").InnerText, out max))
                {
                    this.Width = (min < max) ? rnd.Next(min, max) : 0;
                }
                else
                {
                    this.Width = (int.TryParse(xmlNode.InnerText, out width)) ? width : 0;
                }

                xmlNode = xmlElement.SelectSingleNode("/ScreenGenie/Layout/Size/Height");
                if (xmlNode.Attributes.GetNamedItem("random").InnerText.ToLower() == "true" && int.TryParse(xmlNode.Attributes.GetNamedItem("min").InnerText, out min) && int.TryParse(xmlNode.Attributes.GetNamedItem("max").InnerText, out max))
                {
                    this.Height = (min < max) ? rnd.Next(min, max) : 0;
                }
                else
                {
                    this.Height = (int.TryParse(xmlNode.InnerText, out height)) ? height : 0;
                }

                xmlNode = xmlElement.SelectSingleNode("/ScreenGenie/Layout/WindowState");
                if (xmlNode.InnerText.ToLower() == "normal") { this.WindowState = FormWindowState.Normal; } else { this.WindowState = FormWindowState.Maximized; }
            }
            catch
            {
                return false;
            }
            
            return true;
        }

        private void showMouse()
        {
            Cursor.Show();
        }

        private void sleep(int _delayMS)
        {
            if (_delayMS == 0) { Application.DoEvents(); return; }

            int startTick = GetTickCount();
            while (GetTickCount() - startTick < _delayMS) { Application.DoEvents(); }
        }

        private void xmlParse(string _type, System.Xml.XmlNode _xmlNode)
        {
            int durationS, delayMS, colorDistance, increments, minRadius, maxRadius;
            int minR, minG, minB, maxR, maxG, maxB, minWidth, maxWidth, minHeight, maxHeight;
            bool fill, altColors;
            
            try { int.TryParse(_xmlNode.SelectSingleNode("DurationSeconds").InnerText, out durationS); } catch { durationS = DEFAULT_durationS; }
            try { int.TryParse(_xmlNode.SelectSingleNode("FrameDelayMilliseconds").InnerText, out delayMS); } catch { delayMS = DEFAULT_delayMS; }
            try { int.TryParse(_xmlNode.SelectSingleNode("DistanceBetweenColors").InnerText, out colorDistance); } catch { colorDistance = DEFAULT_colorDistance; }
            try { int.TryParse(_xmlNode.SelectSingleNode("IncrementsPerColor").InnerText, out increments); } catch { increments = DEFAULT_increments; }
            try { int.TryParse(_xmlNode.SelectSingleNode("MinRadius").InnerText, out minRadius); } catch { minRadius = DEFAULT_minRadius; }
            try { int.TryParse(_xmlNode.SelectSingleNode("MaxRadius").InnerText, out maxRadius); } catch { maxRadius = DEFAULT_maxRadius; }
            try { int.TryParse(_xmlNode.SelectSingleNode("MinWidth").InnerText, out minWidth); } catch { minWidth = DEFAULT_minWidth; }
            try { int.TryParse(_xmlNode.SelectSingleNode("MaxWidth").InnerText, out maxWidth); } catch { maxWidth = DEFAULT_maxWidth; }
            try { int.TryParse(_xmlNode.SelectSingleNode("MinHeight").InnerText, out minHeight); } catch { minHeight = DEFAULT_minHeight; }
            try { int.TryParse(_xmlNode.SelectSingleNode("MaxHeight").InnerText, out maxHeight); } catch { maxHeight = DEFAULT_maxHeight; }
            try { int.TryParse(_xmlNode.SelectSingleNode("MinRGB/R").InnerText, out minR); } catch { minR = DEFAULT_minR; }
            try { int.TryParse(_xmlNode.SelectSingleNode("MinRGB/G").InnerText, out minG); } catch { minG = DEFAULT_minG; }
            try { int.TryParse(_xmlNode.SelectSingleNode("MinRGB/B").InnerText, out minB); } catch { minB = DEFAULT_minB; }
            try { int.TryParse(_xmlNode.SelectSingleNode("MaxRGB/R").InnerText, out maxR); } catch { maxR = DEFAULT_maxR; }
            try { int.TryParse(_xmlNode.SelectSingleNode("MaxRGB/G").InnerText, out maxG); } catch { maxG = DEFAULT_maxG; }
            try { int.TryParse(_xmlNode.SelectSingleNode("MaxRGB/B").InnerText, out maxB); } catch { maxB = DEFAULT_maxB; }
            try { fill = (_xmlNode.SelectSingleNode("Fill").InnerText.ToLower() == "true") ? true : false; } catch { fill = false; }
            try { altColors = (_xmlNode.SelectSingleNode("AlternateColors").InnerText.ToLower() == "true") ? true : false; } catch { altColors = false; }

            if (durationS < 0) durationS = 0;
            if (delayMS < 0) delayMS = 0;
            if (minRadius < 0) minRadius = 0; if (maxRadius < 0) maxRadius = 0; if (maxRadius < minRadius) maxRadius = minRadius;
            if (minWidth < 0) minWidth = 0; if (maxWidth < 0) maxWidth = 0; if (maxWidth < minWidth) maxWidth = minWidth;
            if (minHeight < 0) minHeight = 0; if (maxHeight < 0) maxHeight = 0; if (maxHeight < minHeight) maxHeight = minHeight;
            minR = clamp(minR, 0, 255); maxR = clamp(maxR, 0, 255); if (maxR < minR) maxR = minR;
            minG = clamp(minG, 0, 255); maxG = clamp(maxG, 0, 255); if (maxG < minG) maxG = minG;
            minB = clamp(minB, 0, 255); maxB = clamp(maxB, 0, 255); if (maxB < minB) maxB = minB;

            switch (_type)
            {
                case "drawCircles":
                    drawCircles(durationS, delayMS, minRadius, maxRadius, new RGB(minR, minG, minB), new RGB(maxR, maxG, maxB), fill, altColors);
                    break;
                case "drawColor_Fill":
                    drawColor_Fill(durationS, delayMS, new RGB(minR, minG, minB), new RGB(maxR, maxG, maxB), altColors);
                    break;
                case "drawColor_Gradient":
                    drawColor_Gradient(durationS, delayMS, new RGB(minR, minG, minB), new RGB(maxR, maxG, maxB), colorDistance, increments, altColors);
                    break;
                case "drawEllipses":
                    drawEllipses(durationS, delayMS, minWidth, maxWidth, minHeight, maxHeight, new RGB(minR, minG, minB), new RGB(maxR, maxG, maxB), fill, altColors);
                    break;
                case "drawLines_Diagonals":
                    drawLines_Diagonals(durationS, delayMS, new RGB(minR, minG, minB), new RGB(maxR, maxG, maxB), altColors);
                    break;
                case "drawLines_ScrollDown":
                    drawLines_ScrollDown(durationS, delayMS, new RGB(minR, minG, minB), new RGB(maxR, maxG, maxB), altColors);
                    break;
                case "drawLines_ScrollLeft":
                    drawLines_ScrollLeft(durationS, delayMS, new RGB(minR, minG, minB), new RGB(maxR, maxG, maxB), altColors);
                    break;
                case "drawLines_ScrollRight":
                    drawLines_ScrollRight(durationS, delayMS, new RGB(minR, minG, minB), new RGB(maxR, maxG, maxB), altColors);
                    break;
                case "drawLines_ScrollUp":
                    drawLines_ScrollUp(durationS, delayMS, new RGB(minR, minG, minB), new RGB(maxR, maxG, maxB), altColors);
                    break;
                case "drawRectangles":
                    drawRectangles(durationS, delayMS, minWidth, maxWidth, minHeight, maxHeight, new RGB(minR, minG, minB), new RGB(maxR, maxG, maxB), fill, altColors);
                    break;
            }
        }
    }
}
